﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using DBUtil;
using NewLIMS_DataSync.Entry;

namespace NewLIMS_DataSync
{
    public class DataSync : ServiceBase
    {
        public static Timer timer = new Timer();
        public static double interval = (1000 * 60) * 5; // 5 分钟 间隔执行
        /// <summary>
        /// 每次限定最多 多少条数据数据传输
        /// </summary>
        public static int Upload_LimitCount = 5;
        public static int Download_LimitCount = 5;

        /// <summary>
        /// 如果 间隔执行设定修改，则在下次执行更新间隔时间段
        /// </summary>
        private void RefashInterval()
        {
            ConfigurationManager.RefreshSection("connectionStrings");
            ConfigurationManager.RefreshSection("appSettings");

            interval = Utils.ConvertTo<double>(ConfigurationManager.AppSettings["Interval"], 1);

            Upload_LimitCount = Utils.ConvertTo<int>(ConfigurationManager.AppSettings["Upload_LimitCount"], 5);

            Download_LimitCount = Utils.ConvertTo<int>(ConfigurationManager.AppSettings["Download_LimitCount"], 5);

            timer.Interval = interval * (1000 * 60);
        }

        protected override void OnStart(string[] args)
        {
            RefashInterval();
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Start();
            LogUtils.LogInfo("新系统 数据同步服务 开始", Developer.MJ);
        }

        static object locker = new object();
        static int Switch = 0;
        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            lock (locker)
            {
                RefashInterval();

                //if (Switch == 0)
                {
                    try
                    {
                        //上传
                        SyncUpload();
                    }
                    catch (Exception ex)
                    {
                        LogUtils.LogError("新系统 数据同步服务 上传异常", Developer.MJ, ex, ex.InnerException);
                    }
                    Switch = 1;
                }
                //else
                //{
                //    try
                //    {
                //        //下发
                //        SyncDownload();
                //    }
                //    catch (Exception ex)
                //    {
                //        LogUtils.LogError("新系统 数据同步服务 下发异常", Developer.MJ, ex, ex.InnerException);
                //    }
                //    Switch = 0;
                //}
            }
        }

        protected override void OnStop()
        {
            LogUtils.LogInfo("新系统 数据同步服务 停止", Developer.MJ);
        }

        protected override void OnShutdown()
        {
            LogUtils.LogInfo("新系统 数据同步服务 关闭", Developer.MJ);
        }

        /// <summary>
        /// 上传数据
        /// </summary>
        public void SyncUpload()
        {
            SyncConfig configUp = SyncHelper.GetConfig(SyncMode.上传);

            //每次处理 Upload_LimitCount 条
            DBSession dbOra = new DBSession(DataBaseType.Oracle);

            Dictionary<string, string> dictSyncNames = SyncHelper.GetSyncTabNames(SyncMode.上传);
            int cteCount = 0;

            foreach (var entry in dictSyncNames)
            {
                string tbName = entry.Key;
                //获取开始同步时间
                string whereTime = entry.Value;

                string sel_sql = "Select {0} From {1} Where 1=1 and {2}<={3} {4} {5} Order By {6} Asc";
                string lmtType = configUp.LmtType.ToString();
                SyncParams para = configUp.Config.Find(t => t.SourceTbName.Equals(tbName, StringComparison.OrdinalIgnoreCase));
                string[] excludeColNames = para.ExcludeColNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                sel_sql = string.Format(sel_sql, para.SelectColNames, tbName, lmtType, Upload_LimitCount, para.WhereDef, whereTime, para.SignColName);

                sel_sql = "Select * From Lims_Sendreportqueue Where 1=1 And Rownum<10 and state=1 and upstate=0 order by queuetime asc ";
                DataTable data = dbOra.QueryTable(sel_sql);
                bool isOk = false;
                if (data == null || data.Rows.Count <= 0)
                {
                    cteCount++;
                }
                else
                {
                    var lstUniqueVal = DBUtil.DBUtil.GetFirstCol<string>(data, para.UniqueColName);
                    LogUtils.LogInfo("新系统 数据同步服务  上传开始", Developer.MJ, "本次同步" + tbName + "：" + data.Rows.Count + "条", lstUniqueVal.ToArray());
                    DelegateSynService.DelegateSynchronizationClient synClient = new DelegateSynService.DelegateSynchronizationClient();
                    string msg = string.Empty;
                    isOk = synClient.UpData(data, para.MapperTbName, para.UniqueColName, excludeColNames);                    
                    if (!isOk)
                    {
                        isOk = synClient.SyncData(out msg, data, para.MapperTbName, true);
                    }
                    object signColVal = data.Rows[data.Rows.Count - 1][para.SignColName];
                    if (isOk)
                    {
                        SyncHelper.SaveTimeSP(tbName, SyncMode.上传, signColVal);

                        //用时间戳同步更新遇到问题，现使用 增加upState 字段， 上传成功，更新报告的 UpState状态未 1，每次上传  UpState=0 的数据。
                        int upOk = -1;
                        foreach (DataRow dr in data.Rows)
                        {
                            string idStr = dr["Id"].ToString();
                            string selectNo = dr["selectno"].ToString();
                            Hashtable ht = new Hashtable();
                            ht.Add("Id", idStr);
                            ht.Add("Selectno", selectNo);
                            ht.Add("queuetime",DateTime.Now);
                            ht.Add("UpState", 1);
                            upOk = dbOra.Update(ht, "lims_sendreportqueue", "ID", null);
                        }
                    }
                    LogUtils.LogInfo("新系统 数据同步服务  上传完成", Developer.MJ, "本次同步" + tbName + "结果：" + isOk, "最后时间戳：" + signColVal, "错误信息：" + msg);
                     var dictTsp = data.GetDict<string, string>(para.UniqueColName, para.SignColName);
                    LogUtils.LogInfo("同步 上传时间戳", Developer.MJ, dictTsp);
                }
            }
            if (cteCount == dictSyncNames.Count)
            {
                LogUtils.LogInfo("新系统 数据同步服务 上传Sleep", Developer.MJ, "休眠：3000ms");
                System.Threading.Thread.Sleep(3000);
            }

        }

        /// <summary>
        /// 下发
        /// </summary>
        public void SyncDownload()
        {
            //每次处理 Download_LimitCount 条
            DelegateSynService.DelegateSynchronizationClient synClient = new DelegateSynService.DelegateSynchronizationClient();

            SyncConfig configDown = SyncHelper.GetConfig(SyncMode.下发);
            Dictionary<string, string> dictSyncNames = SyncHelper.GetSyncTabNames(SyncMode.下发);

            foreach (var entry in dictSyncNames)
            {
                string tbName = entry.Key;
                //获取开始同步时间
                string whereTime = entry.Value;

                string sel_sql = "select {0} from {1} where 1=1 {2} {3} order by {4} asc LIMIT {5}";
                string lmtType = configDown.LmtType.ToString();
                SyncParams para = configDown.Config.Find(t => t.SourceTbName.Equals(tbName, StringComparison.OrdinalIgnoreCase));
                string[] excludeColNames = para.ExcludeColNames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                sel_sql = string.Format(sel_sql, para.SelectColNames, tbName, para.WhereDef, whereTime, para.SignColName, Download_LimitCount);

                DataTable data = synClient.QueryTable(sel_sql, 300);
                List<Hashtable> lstHt = ConvertHashtable(data);
                if (lstHt == null || lstHt.Count <= 0)
                {
                    LogUtils.LogInfo("新系统 数据同步服务 下发Sleep", Developer.MJ, "休眠：3000ms");
                    System.Threading.Thread.Sleep(3000);
                }
                else
                {
                    DBSession dbOra = new DBSession(DataBaseType.Oracle);
                    int res = -1;
                    bool isOk = false;
                    var lstCodes = DBUtil.DBUtil.GetFirstCol<string>(data, para.UniqueColName);
                    LogUtils.LogInfo("新系统 数据同步服务 下发开始", Developer.MJ, "本次下发" + tbName + "：" + data.Rows.Count + "条", lstCodes.ToArray());
                    string uniqueVal = string.Empty, exist_sql = string.Empty;
                    try
                    {

                        foreach (Hashtable ht in lstHt)
                        {
                            uniqueVal = ht[para.UniqueColName].ToString();
                            exist_sql = "select count(1) from {0} where {1}='{2}' ";
                            exist_sql = string.Format(exist_sql, para.MapperTbName, para.UniqueColName, uniqueVal);
                            if (dbOra.Exists(exist_sql))
                            {
                                res = dbOra.Update(ht, para.MapperTbName, para.UniqueColName, excludeColNames);
                            }
                            else
                            {
                                isOk = dbOra.Insert(ht, para.MapperTbName, excludeColNames);
                            }
                        }
                        object signColVal = lstHt[lstHt.Count - 1][para.SignColName];
                        SyncHelper.SaveTimeSP(tbName, SyncMode.下发, signColVal);
                        LogUtils.LogInfo("新系统 数据同步服务 下发结束", Developer.MJ, "本次下发完成(" + tbName + ")", "最后时间戳：" + signColVal);

                        var dictTsp = data.GetDict<string, string>(para.UniqueColName, para.SignColName);
                        LogUtils.LogInfo("同步 下发时间戳", Developer.MJ, dictTsp);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }
        }

        private List<Hashtable> ConvertHashtable(DataTable data)
        {
            List<Hashtable> lstHt = new List<Hashtable>();
            foreach (DataRow dr in data.Rows)
            {
                Hashtable ht = new Hashtable(StringComparer.OrdinalIgnoreCase);
                foreach (DataColumn dc in data.Columns)
                {
                    object value = dr[dc.ColumnName];
                    ht.Add(dc.ColumnName, value);
                }
                lstHt.Add(ht);
            }
            return lstHt;
        }
    }
}
